package com.youbenzi.dockerpool.factory;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.apache.commons.io.FileUtils;

import com.spotify.docker.client.DefaultDockerClient;
import com.spotify.docker.client.DockerClient;
import com.spotify.docker.client.exceptions.DockerCertificateException;
import com.spotify.docker.client.exceptions.DockerException;
import com.spotify.docker.client.messages.ContainerConfig;
import com.spotify.docker.client.messages.HostConfig;
import com.spotify.docker.client.messages.PortBinding;
import com.youbenzi.dockerpool.AbstractDockerFactory;

/**
 * jenkins docker 工厂
 * @author yangyingqiang
 * @time 2017年6月9日 下午6:25:54
 */
public class JenkinsDockerFactory extends AbstractDockerFactory{

	private static final String ROOT_DIR;
	
	static {
		Properties properties = new Properties();
		try {
			properties.load(JenkinsDockerFactory.class.getResourceAsStream("/jenkins-docker.properties"));
		} catch (IOException e) {
			e.printStackTrace();
		}
		ROOT_DIR = properties.getProperty("rootDir");
	}
	
	/**
	 * jenkins home根目录，所有的docker的jenkins_home 目录都创建在这个目录内
	 */
	private static final String JENKINS_HOME_ROOT = ROOT_DIR + "/jenkins-home-users";
	
	private static final String GRADLE_HOME = ROOT_DIR + "/env/gradle-3.5";
	private static final String MAVEN_HOME = ROOT_DIR + "/env/apache-maven-3.5.0";
	
	private static final Map<String, JenkinsEnvSetting> SETTINGS = new HashMap<String, JenkinsEnvSetting>() {
		private static final long serialVersionUID = -5934420025991028285L;
		{
			put("jdk7", new JenkinsEnvSetting("jdk7", 
					ROOT_DIR + "/env/jdk1.7.0_80", 
					ROOT_DIR + "/env/jenkins-home-jdk7"));
//			put("jdk8", new EnvSetting("jdk8", 
//					ROOT_DIR + "/env/jdk1.8.0_131", 
//					ROOT_DIR + "/env/jenkins-home-jdk7"));
		}
	};
	
	@Override
	public void createAndStartContainer(String type, String host, int visitPort, 
			DockerClient docker) throws IOException, DockerException, InterruptedException {

		String containerName = containerName(type, host, visitPort);
		JenkinsEnvSetting envSetting = SETTINGS.get(type);
		String[] ports = {"8080", "50000"};
		String[] host_Ports = {visitPort + "", (visitPort + 50000) + ""};
		Map<String, List<PortBinding>> portBindings = new HashMap<>();
		for (int i=0; i<ports.length; i++) {
			String port = ports[i];
		    List<PortBinding> hostPorts = new ArrayList<>();
		    hostPorts.add(PortBinding.of("0.0.0.0", host_Ports[i]));
		    portBindings.put(port, hostPorts);
		}
		HostConfig hostConfig = HostConfig.builder().binds(
				jenkinHome(envSetting, containerName) + ":/var/jenkins_home",
				envSetting.getJdkHome() + ":/var/jdk",
				GRADLE_HOME + ":/var/gradle_home",
				MAVEN_HOME + ":/var/maven_home"
				).portBindings(portBindings)
				.build();
		
		ContainerConfig config = ContainerConfig.builder().hostConfig(hostConfig)
			.image("oschina/jenkins-jdk:1.1")
			.exposedPorts(ports)
			.build();
		docker.createContainer(config, containerName);
		docker.startContainer(containerName);
	}

	@Override
	public void removeContainer(String type, String host, int visitPort) {
		String containerName = containerName(type, host, visitPort);
		try (DockerClient docker = DefaultDockerClient.fromEnv().build()) {
			try {
				docker.killContainer(containerName);
			} catch (DockerException | InterruptedException e) {
				e.printStackTrace();
			}
			try {
				docker.removeContainer(containerName);
			} catch (DockerException | InterruptedException e) {
				e.printStackTrace();
			}
		} catch (DockerCertificateException e) {
			e.printStackTrace();
		}
		File target = new File(JENKINS_HOME_ROOT + "/" + containerName);
		if(target.exists()) {
			try {
				FileUtils.deleteDirectory(target);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	@Override
	public String[] types() {
		Set<String> keys = SETTINGS.keySet();
		return SETTINGS.keySet().toArray(new String[keys.size()]);
	}
	
	private String jenkinHome(JenkinsEnvSetting envSetting, String containerName) throws IOException {
		String dir = JENKINS_HOME_ROOT + "/" + containerName;
		
		File target = new File(dir);
		target.mkdirs();
		FileUtils.copyDirectory(new File(envSetting.getJenkinsHome()), target);
		
		return dir;
	}
	
	@Override
	public String containerName(String type, String host, int visitPort) {
		return type + "_" + host + "_" + visitPort;
	}

	@Override
	public boolean isFullyUpByLogInfo(String logInfo) {
		return logInfo.indexOf("INFO: Jenkins is fully up and running") > -1;
	}

	public static void main(String[] args) throws IOException {
	}

}
